Skip to content

Resolve siteId dynamically via x-site-id header for multisite#3700

Merged
unandyala merged 17 commits intofeature/httponly-session-cookiesfrom
unandyala.handle-dynamic-site-id
Mar 5, 2026
Merged

Resolve siteId dynamically via x-site-id header for multisite#3700
unandyala merged 17 commits intofeature/httponly-session-cookiesfrom
unandyala.handle-dynamic-site-id

Conversation

@unandyala
Copy link
Contributor

@unandyala unandyala commented Mar 2, 2026

Summary

  • Adds x-site-id header to CommerceApiProvider headers from the per-request resolved locals.site?.id, so every SDK request carries the correct siteId
  • Updates SLAS private proxy (build-remote-server.js), token response processing (process-token-response.js), and regular proxy auth (configure-proxy.js) to prefer x-site-id header over static config siteId, with static config as fallback for backwards compatibility
  • Fixes HttpOnly cookie lookups (cc-at_{siteId}, cc-nx_{siteId}) that were always using the default site's ID, breaking token injection for non-default sites in multisite setups
httponly-multisite.mov

Test plan

  • process-token-response.test.js — 22/22 passed (2 new: header override + fallback)
  • configure-proxy.basic.test.js — 12/12 passed (2 new: header override + fallback)
  • build-remote-server.test.js — 54/54 passed (1 new: header precedence over static config for logout)
  • Manual verification with multisite config using non-default site

🤖 Generated with Claude Code

unandyala and others added 2 commits March 2, 2026 13:18
…logout

When HttpOnly session cookies are enabled, the shopper's access token and
refresh token are stored in HttpOnly cookies and are not accessible to
client-side JavaScript. The SLAS /oauth2/logout endpoint requires both
a Bearer token in the Authorization header and a refresh_token query
parameter. This change injects both from HttpOnly cookies in the SLAS
private client proxy.

Also moves SLAS-specific Bearer token logic out of configure-proxy.js
(regular /mobify/proxy path) into the SLAS private client proxy where
it belongs, since SLAS calls don't go through the regular proxy when
useSLASPrivateClient is enabled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
With multisite enabled, siteId is request-dependent but was previously
read once at startup from static config, breaking HttpOnly cookie lookups
for non-default sites. This adds an x-site-id header from the per-request
resolved site and reads it in the proxy layers with static config fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cc-prodsec
Copy link
Collaborator

cc-prodsec commented Mar 2, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

resolveSiteFromUrl already falls back to the default site, so the
x-site-id header always carries a valid value. Remove the static config
fallback and the now-unused siteId parameter from the proxy chain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@vcua-mobify vcua-mobify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for following up on this. Using a header to pass in the site id seems like a good approach to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an _app-config change, we'll want to update the _app-config templates in the generator.

We'll probably also need to let existing projects that are consuming this change know that they need to add this header

unandyala and others added 10 commits March 2, 2026 21:30
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eck, warn on missing x-site-id

Only invoke applyScapiAuthHeaders when HttpOnly session cookies are
enabled. Remove the unnecessary SLAS auth endpoint guard since SLAS
requests use a separate proxy. Log a warning when x-site-id header
is missing on SCAPI requests to aid debugging if the template is
misconfigured.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tract injectLogoutTokens

The option only matches the logout endpoint and injects both Bearer
token and refresh token, so the old name was misleading. Extract the
inline logout injection logic into a standalone injectLogoutTokens
function for clarity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Base automatically changed from unandyala.handle-logout to feature/httponly-session-cookies March 4, 2026 18:04
* sets the Authorization header, and appends refresh_token to the query string.
* @private
*/
export const injectLogoutTokens = (proxyRequest, incomingRequest) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor refactor - moved to a separate function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this function be moved into process-token-response?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not really related to processing the response. Other option is to rename process-token-response to a more generic one - httponly-cookie-utils and then move this function. I will take another look and see if it make sense to rename

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will leave it as is for now and consider rename/refactor as we make more changes

@unandyala unandyala marked this pull request as ready for review March 4, 2026 19:20
@unandyala unandyala requested a review from a team as a code owner March 4, 2026 19:20
Copy link
Contributor

@vcua-mobify vcua-mobify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes @unandyala !

Just a few more comments then I think this is ready

}
}
}
injectLogoutTokens(proxyRequest, incomingRequest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we make this func a bit clearer: injectTokenToLogoutEndpoint? and it would be helpful to explain why

// SLAS log out endpoint requires token and refresh token in the body, the other SLAS does not need to pass token in the body
injectTokenToLogoutEndpoint(...)

@unandyala unandyala merged commit c45512d into feature/httponly-session-cookies Mar 5, 2026
73 of 74 checks passed
@unandyala unandyala deleted the unandyala.handle-dynamic-site-id branch March 5, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants